/************************************************************************
Copyright (c) 2010, 2013, C.R. All rights reserved. 

E-mail: crtoyou@gmail.com; crtoyou@163.com

You can redistribute it and/or modify it under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation version 3 of the License.

This source code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. if not, write to the Free Software Foundation, Inc., 
51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
************************************************************************/

#ifndef __CR_FILE_PATH_UTILLITY_H__
#define __CR_FILE_PATH_UTILLITY_H__

#include <Windows.h>

namespace cr{

struct path_wrap
{
	TCHAR path[_MAX_PATH];
	TCHAR drive[_MAX_DRIVE];
	TCHAR dir[_MAX_DIR];
	TCHAR fname[_MAX_FNAME];
	TCHAR ext[_MAX_EXT];
	inline errno_t splitpath(LPCTSTR _path = NULL)
	{
		if (_path)
		{
			while (*_path == _T('\"'))
				_path++;
			_tcscpy_s<_MAX_PATH>(path, _path);
			TCHAR* qpos = _tcschr(path, _T('\"'));
			if (qpos)
				*qpos = NULL;
		}
		return _tsplitpath_s<_MAX_DRIVE,_MAX_DIR,_MAX_FNAME,_MAX_EXT>(path, drive, dir, fname, ext);
	}
};

struct module_path : public path_wrap
{
	module_path()
	{
		GetModuleFileName(0, path, _MAX_PATH);
		splitpath();
	}
};

BOOL FileExist(LPCTSTR path)
{
	if (!path || !path[0])
		return FALSE;
	WIN32_FIND_DATA fd;
	HANDLE hFind = FindFirstFile(path, &fd);
	if (hFind == INVALID_HANDLE_VALUE)
		return FALSE;
	FindClose(hFind);
	return TRUE;
}

singleton<module_path> the_module_path;

}//namespace

#endif//__CR_FILE_PATH_UTILLITY_H__
//
//#pragma once
//#include "import/md5.h"
//#include <shlobj.h>
//#include <shellapi.h>
//
//namespace cr {
//
//#pragma comment(lib, "version")
//static HRESULT GetFileVersion(LPCTSTR lpszFileName, VS_FIXEDFILEINFO * lpVersion)
//{
//	VS_FIXEDFILEINFO *pVerInfo = NULL;
//	DWORD dwTemp, dwSize, dwHandle = 0;
//	BYTE *pData = NULL;
//	UINT uLen;
//	if (!::PathFileExists(lpszFileName))
//	{
//		return E_FAIL;
//	}
//	dwSize = ::GetFileVersionInfoSize(lpszFileName, &dwTemp);
//	if (dwSize == 0)
//	{
//		return E_INVALIDARG;
//	}
//
//	pData = new BYTE[dwSize];
//	if (pData == NULL)
//	{
//		return E_OUTOFMEMORY;
//	}
//
//	if (!::GetFileVersionInfo(lpszFileName, dwHandle, dwSize, pData))
//	{
//		delete [] pData;
//		return E_FAIL;
//	}
//
//	if (!::VerQueryValue(pData, _T("\\"), (void **) &pVerInfo, &uLen)) 
//	{
//		delete [] pData;
//		return E_FAIL;
//	}
//
//	if (lpVersion)
//		RtlCopyMemory(lpVersion, pVerInfo, sizeof(VS_FIXEDFILEINFO));
//	delete [] pData;
//
//	return S_OK;
//}
//static bool VersionStringToNumber(const string & version, DWORD * pNumber)
//{
//	DWORD dw0 = 0, dw1 = 0, dw2 = 0, dw3 = 0;
//	const char * psz = version.c_str();
//	dw0 = atoi(psz);
//	if (psz = strchr(psz, '.'))
//	{
//		dw1 = atoi(++psz);
//		if (psz = strchr(psz, '.'))
//		{
//			dw2 = atoi(++psz);
//			if (psz = strchr(psz, '.'))
//				dw3 = atoi(++psz);
//		}
//	}
//	if (pNumber)
//	{
//		pNumber[0] = MAKELONG(dw1, dw0);
//		pNumber[1] = MAKELONG(dw3, dw2);
//	}
//	return true;
//}
//static string ExtractResourceToString(LPCTSTR lpszType, LPCTSTR lpszResName, HMODULE hModule)
//{
//	string strOut;
//	HRSRC hRes = ::FindResource(hModule, lpszResName, lpszType);
//	if (hRes == NULL)
//	{
//		return strOut;
//	}
//	DWORD dwSize = ::SizeofResource( hModule, hRes); 
//	if (dwSize == 0)
//	{
//		return strOut;
//	}
//	HGLOBAL hGlobal = ::LoadResource( hModule, hRes); 
//	if (hGlobal == NULL)
//	{
//		return strOut;
//	}
//	LPVOID pBuffer = ::LockResource(hGlobal); 
//	if (pBuffer == NULL)
//	{
//		::FreeResource(hGlobal); 
//		return strOut;
//	}
//	strOut.assign(reinterpret_cast<LPCSTR>(pBuffer), dwSize);
//	::FreeResource(hGlobal); 
//	return strOut;
//}
//
//class Env
//{
//public:
//	static tstring GetAppDirectory(LPCTSTR szMore = NULL, BOOL isDirectory = TRUE)
//	{
//		TCHAR szDirectory[MAX_PATH];
//		::GetModuleFileName(NULL, szDirectory, _countof(szDirectory));
//		::PathAppend(szDirectory, _T(".."));
//		if (szMore)
//		{
//			::PathAppend(szDirectory, szMore);
//			if (isDirectory)
//				CreateDirectoryRecursive(szDirectory);
//		}
//		return szDirectory;
//	}
//	static void AppendPath(tstring & strBase, const tstring & strMore)
//	{
//		int n = strBase.size() + strMore.size() + 10;
//		strBase.resize(n);
//		::PathAppend(const_cast<LPTSTR>(strBase.c_str()), strMore.c_str());
//		strBase.resize(_tcslen(strBase.c_str()));
//	}
//	static tstring GetAppData(BOOL isLocal = FALSE, LPCTSTR szMore = NULL)
//	{
//		TCHAR szPath[MAX_PATH];
//		::SHGetSpecialFolderPath(NULL, szPath, isLocal?CSIDL_LOCAL_APPDATA:CSIDL_APPDATA, TRUE);
//		::PathAppend(szPath, PATH_ROOT);
//		if (szMore)
//			::PathAppend(szPath, szMore);
//		CreateDirectoryRecursive(szPath);
//		return szPath;
//	}
//
//	static bool FileExist(LPCTSTR pszFileName)
//	{
//		_ASSERTE(!::IsBadStringPtr(pszFileName, MAX_PATH));
//		DWORD dwErrMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
//		DWORD dwAttribs = ::GetFileAttributes(pszFileName);
//		::SetErrorMode(dwErrMode);
//		return (dwAttribs != INVALID_FILE_ATTRIBUTES) && ((dwAttribs & FILE_ATTRIBUTE_DIRECTORY) == 0);
//	}
//	static bool DirExist(LPCTSTR pszDirName)
//	{
//		_ASSERTE(!::IsBadStringPtr(pszDirName, MAX_PATH));
//		DWORD dwErrMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
//		DWORD dwAttribs = ::GetFileAttributes(pszDirName);
//		::SetErrorMode(dwErrMode);
//		return (dwAttribs != INVALID_FILE_ATTRIBUTES) && (dwAttribs & FILE_ATTRIBUTE_DIRECTORY);
//	}
//	static bool FileDelete(LPCTSTR szFile, bool bAllowDelay = true)
//	{
//		if (::DeleteFile(szFile))
//			return true;
//		switch (::GetLastError())
//		{
//		case ERROR_FILE_NOT_FOUND:
//			return true;
//		case ERROR_ACCESS_DENIED:
//			{
//				DWORD dwAttribs = ::GetFileAttributes(szFile);
//				if (dwAttribs & FILE_ATTRIBUTE_READONLY)
//				{
//					dwAttribs &= 0xFFFFFF00;
//					dwAttribs |= FILE_ATTRIBUTE_NORMAL;
//					::SetFileAttributes(szFile, dwAttribs);
//					return ::DeleteFile(szFile)?true:false;
//				}
//			}
//			return false;
//		}
//		if (bAllowDelay)
//			if (::MoveFileEx(szFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT))
//				return true;
//		return false;
//	}
//	static bool DirDelete(LPCTSTR szDir)
//	{
//		SHFILEOPSTRUCT file_op = {
//			NULL,
//			FO_DELETE,
//			szDir,
//			_T(""),
//			FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT,
//			false,
//			0,
//			_T("") };
//			if (SHFileOperation(&file_op) == 0)
//				return true;
//			return false;
//	}
//	static bool FileMove(LPCTSTR szOld, LPCTSTR szNew)
//	{
//		if (FileExist(szNew))
//		{
//			if (!FileDelete(szNew, false))
//			{
//				// delete operation failed
//				// szNew is occupied
//				// try to rename it
//				TCHAR szTmp[MAX_PATH];
//				_tcscpy_s(szTmp, szNew);
//				_tcscat_s(szTmp, _T(".tmp"));
//				if (!::MoveFileEx(szNew, szTmp, MOVEFILE_REPLACE_EXISTING))
//					return false;
//			}
//		}
//		else
//		{
//			TCHAR szTmp[MAX_PATH];
//			_tcscpy_s(szTmp, szNew);
//			::PathAppend(szTmp, _T(".."));
//			CreateDirectoryRecursive(szTmp);
//		}
//		return ::MoveFile(szOld, szNew)?true:false;
//	}
//	static DWORD CreateDirectoryRecursive(LPCTSTR pszDirName)
//	{
//		if (DirExist(pszDirName))
//			return ERROR_SUCCESS;
//		tstring sDirName(pszDirName);
//		int iLength = sDirName.size();
//		int i = 0;
//		DWORD dwError;
//		if ((iLength > 2) && (sDirName[1] == _T(':')))
//		{
//			i = 3;
//		}
//		for (; i<iLength; i++)
//		{
//			if (sDirName[i] == _T('\\'))
//			{
//				tstring sDirectoryName = sDirName.substr(0, i);
//
//				if (DirExist(sDirectoryName.c_str()))
//					continue;
//				if (::CreateDirectory(sDirectoryName.c_str(), NULL))
//					dwError = ERROR_SUCCESS;
//				else
//					dwError = ::GetLastError();
//				if (dwError)
//					return dwError;
//			}
//		}
//		if (!DirExist(sDirName.c_str()))
//			return ::CreateDirectory(sDirName.c_str(), NULL)?ERROR_SUCCESS:(::GetLastError());
//		return ERROR_SUCCESS;
//	}
//	static BOOL Start(LPCTSTR szCommand, BOOL bWaitForQuit = TRUE)
//	{
//		TCHAR szCmdLine[500];
//		STARTUPINFO si = {0};
//		PROCESS_INFORMATION pi = {0};
//		si.cb = sizeof(STARTUPINFO);
//		_tcscpy_s(szCmdLine, szCommand);
//		if (::CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
//		{
//			if (bWaitForQuit)
//				::WaitForSingleObject( pi.hProcess, INFINITE );
//
//			// Close process and thread handles. 
//			::CloseHandle( pi.hProcess );
//			::CloseHandle( pi.hThread );
//			return TRUE;
//		}
//		return FALSE;
//	}
//	static BOOL RegServer(LPCTSTR szDll)
//	{
//		tstring str = _T("regsvr32 /s \"");
//		str.append(szDll);
//		str.append(_T("\""));
//		return Start(str.c_str());
//	}
//};
//
//}//namespace
